package com.techsoft.dataconverter;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URLDecoder;
import java.security.Key;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.techsoft.MetaData;
import com.techsoft.DataConverter;

public class JSONConverter implements DataConverter {
	private static final Logger Log = LoggerFactory
			.getLogger(JSONConverter.class);

	// 密钥
	private final static String secretKey = "liuyunqiang@lx100$#365#$";
	// 向量
	private final static String iv = "01234567";

	// 加解密统一使用的编码方式
	// private final static String encoding = "utf-8";

	public Object serializeList(List<Object> source) {
		JSONArray results = new JSONArray();
		Iterator<Object> iter = source.iterator();
		Object key = null;
		while (iter.hasNext()) {
			key = iter.next();
			results.add(this.serializeObject(key));
		}

		return results;
	}

	public Object serializeMap(Map<String, Object> source) {
		JSONObject result = new JSONObject();
		String key = null;
		Object value = null;
		Iterator<String> keyiter = source.keySet().iterator();
		while (keyiter.hasNext()) {
			key = keyiter.next();
			value = source.get(key);
			result.put(key, this.serializeObject(value));
		}

		return result;
	}

	@Override
	@SuppressWarnings("unchecked")
	public Object serializeObject(Object source) {
		Object result = null;
		SimpleDateFormat dateFormat = null;
		JSONObject json = null;
		MetaData metadata = null;
		if (source == null) {
			result = "";
		} else if (source instanceof java.lang.String) {
			result = source;
		} else if (source instanceof java.util.Date) {
			dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			result = dateFormat.format((java.util.Date) source);
		} else if (source instanceof java.lang.Integer) {
			result = source;
		} else if (source instanceof java.lang.Long) {
			result = source;
		} else if (source instanceof java.lang.Byte) {
			result = source;
		} else if (source instanceof java.lang.Short) {
			result = source;
		} else if (source instanceof java.lang.Float) {
			result = source;
		} else if (source instanceof java.lang.Double) {
			result = source;
		} else if (source instanceof java.math.BigDecimal) {
			result = String.valueOf(source);
		} else if (source instanceof java.math.BigInteger) {
			result = String.valueOf(source);
		} else if (source instanceof java.lang.Boolean) {
			result = String.valueOf(source);
		} else if (source instanceof java.util.Map<?, ?>) {
			return this.serializeMap((java.util.Map<String, Object>) source);
		} else if (source instanceof java.util.List<?>) {
			result = this.serializeList((java.util.List<Object>) source);
		} else if (source instanceof MetaData) {
			json = new JSONObject();
			metadata = (MetaData) source;
			json.put("DTYPENAME", metadata.getDtypename());
			json.put("PRECISION", metadata.getPrecision());
			json.put("SCALE", metadata.getScale());
			json.put("FNAME", metadata.getFname());
			json.put("NULLABLE", metadata.getNullable());
			json.put("MAXLEN", metadata.getMaxlen());
			json.put("DTYPE", metadata.getDtype());
			result = json;
		}

		return result;
	}

	public void writeToOutputStream(Object obj, OutputStream out) {
		if (obj instanceof JSON) {
			String jsonStr = JSONObject
					.toJSONString(
							obj,
							com.alibaba.fastjson.serializer.SerializerFeature.WriteMapNullValue);

			OutputStreamWriter writer = null;
			try {
				writer = new OutputStreamWriter(out);
				writer.write(jsonStr);
				writer.flush();
				writer.close();
			} catch (Exception e) {
				Log.error("JSONAdapter.writeOutputStream方法中出错，原因如下：\n"
						+ e.getMessage());
			} finally {
				try {
					if (writer != null) {
						writer.close();
					}
				} catch (IOException e) {
					Log.error("JSONAdapter.writeOutputStream方法中出错，原因如下：\n"
							+ e.getMessage());
				}
			}

		}
	}

	@Override
	public Object readFromInputStream(InputStream in) throws Exception {
		JSONObject result = null;
		BufferedReader tBufferedReader = new BufferedReader(
				new InputStreamReader(in));
		StringBuffer tStringBuffer = new StringBuffer();
		String sTempOneLine = "";
		try {
			while ((sTempOneLine = tBufferedReader.readLine()) != null) {
				tStringBuffer.append(sTempOneLine);
			}

			String s = URLDecoder.decode(tStringBuffer.toString(),
					System.getProperty("file.encoding"));

			if (s.startsWith("allparams=")) {
				result = JSONObject.parseObject(s.substring(10));
			} else {
				result = JSONObject.parseObject(s);
			}
		} catch (IOException e) {
			Log.error("JSONAdapter.readFromInputStream方法中出错，原因如下：\n"
					+ e.getMessage());
			throw e;
		}

		return result;
	}

	@Override
	public Object deserializeObject(Object source) {
		Object result = null;
		if (source instanceof JSONArray) {
			result = this.deserializeList(source);
		} else if (source instanceof JSONObject) {
			result = this.deserializeMap(source);
		} else {
			result = source;
		}

		return result;
	}

	public List<Object> deserializeList(Object source) {
		List<Object> results = new ArrayList<Object>();
		JSONArray jsonlist = (JSONArray) source;
		Iterator<Object> iter = jsonlist.iterator();
		while (iter.hasNext()) {
			results.add(this.deserializeObject(iter.next()));
		}
		return results;
	}

	public Map<String, Object> deserializeMap(Object source) {
		Map<String, Object> result = new HashMap<String, Object>();
		JSONObject json = (JSONObject) source;
		Iterator<String> iter = json.keySet().iterator();
		String key = null;
		Object value = null;
		while (iter.hasNext()) {
			key = iter.next();
			value = json.get(key);
			result.put(key, this.deserializeObject(value));
		}
		return result;
	}

	@Override
	public Cipher getOutCipher() throws Exception {
		Key deskey = null;
		DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());
		SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
		deskey = keyfactory.generateSecret(spec);
		Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
		IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
		cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);

		return cipher;
	}

	@Override
	public Cipher getInCipher() throws Exception {
		Key deskey = null;
		DESedeKeySpec spec = new DESedeKeySpec(secretKey.getBytes());
		SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("desede");
		deskey = keyfactory.generateSecret(spec);
		Cipher cipher = Cipher.getInstance("desede/CBC/PKCS5Padding");
		IvParameterSpec ips = new IvParameterSpec(iv.getBytes());
		cipher.init(Cipher.DECRYPT_MODE, deskey, ips);
		return cipher;
	}

	@Override
	public String getPrefix() {
		return null;
	}

	@Override
	public void setPrefix(String prefix) {

	}

}
